package com.spider.admin.service.token;

import com.alibaba.fastjson.JSONObject;
import com.spider.admin.cache.ServiceInfoCacheUtil;
import com.spider.admin.cache.ServiceSettingCacheUtil;
import com.spider.admin.conf.ENVConf;
import com.spider.admin.conf.ResultMessage;
import com.spider.admin.exception.SpiderException;
import com.spider.admin.http.entity.TokenEntity;
import com.spider.admin.store.primary.model.ClientTenantInfo;
import com.spider.admin.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Base64;
import java.util.Map;
import java.util.Set;

@Slf4j
@Service
public class TokenService {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private ServiceSettingCacheUtil serviceSettingCacheUtil;

    @Autowired
    private ServiceInfoCacheUtil serviceInfoCacheUtil;

    @Autowired
    private ENVConf envConf;

    /**
     * 生成Token
     *
     * @param clientKey
     * @return
     * @throws SpiderException
     */
    public Map<String, String> createToken(String clientKey) throws SpiderException {
        String str = new String(Base64.getDecoder().decode(clientKey.getBytes()));
        String clientKeys[] = str.split("~");
        String clientInfoStr = null;
        if (clientKeys != null && clientKeys.length == 2) {
            long l = System.currentTimeMillis();
            long t = Long.parseLong(clientKeys[1]);
            if (t - l > 2000 || t - l < -2000) {
                throw new SpiderException(ResultMessage.FAILED_PARAMS_VALIDATE.getCode(), "获取Token时间戳超时");
            }

            clientInfoStr = (String) serviceSettingCacheUtil.get("token-ckey-" + clientKeys[0]);
        } else {
            clientInfoStr = (String) serviceSettingCacheUtil.get("token-ckey-" + clientKey);
        }
        Map<String, String> token = null;
        if (StringUtils.isNotEmpty(clientInfoStr)) {
            ClientTenantInfo clientTenantInfo = JSONObject.parseObject(clientInfoStr, ClientTenantInfo.class);
            token = jwtUtil.createToken(clientTenantInfo);
        }
        if (token == null || token.isEmpty()) {
            throw new SpiderException(ResultMessage.FAILED_UNAUTHORIZED.getCode(), ResultMessage.FAILED_UNAUTHORIZED.getMessage());
        }
        log.info("为 {} 生成token", clientKey);
        return token;
    }

    /**
     * 验证Token，返回Token解析后的信息
     *
     * @param token
     * @return
     */
    public Map<String, Object> verify(TokenEntity token) throws SpiderException {

        //验证调用地址
        if (StringUtils.isEmpty(token.getAccessUrl()) || StringUtils.isEmpty(token.getToken())) {
            throw new SpiderException(ResultMessage.FAILED_PARAMS_VALIDATE.getCode(), ResultMessage.FAILED_PARAMS_VALIDATE.getMessage());
        }
        String accessUrl = new String(Base64.getUrlDecoder().decode(token.getAccessUrl()));
        accessUrl = accessUrl.endsWith("/") ? accessUrl : accessUrl + "/";
        Set<String> urlSet = serviceInfoCacheUtil.getKeys();
        Map<String, String> serviceInfo = null;
        if (urlSet != null && !urlSet.isEmpty()) {
            for (String url : urlSet) {
                if (accessUrl.startsWith(url)) {
                    serviceInfo = serviceInfoCacheUtil.get(url);
                    break;
                }
            }
        }
        String realUrl = accessUrl;
        if (serviceInfo != null && !serviceInfo.isEmpty()) {
            realUrl = serviceInfo.get(ServiceInfoCacheUtil.SERVICE_URL);
        }
        //验证Token
        Map<String, Object> tokenInfo = jwtUtil.verifyToken(token.getToken());
        tokenInfo.put("requestRealUrl", realUrl);
        boolean throwBol = (boolean) tokenInfo.get("verify");
        if (!throwBol) {
            //Token验证失败
            tokenInfo.put("permsVerify", false);
            return tokenInfo;
        }

        //验证管理客户端
        String tenantKey = (String) tokenInfo.get("tenantKey");
        if (envConf.getClientId().equals(tokenInfo.get("clientId"))) {
            //管理端调用
            tokenInfo.put("permsVerify", true);
            return tokenInfo;
        }

        //验证普通客户端调用服务权限
        String permsStr = (String) serviceSettingCacheUtil.get("perms-" + tenantKey);
        if (StringUtils.isEmpty(permsStr)) {
            tokenInfo.put("permsVerify", false);
            return tokenInfo;
        }
        String[] urls = permsStr.replace("\"", "").replace("'", "").split(",");
        if (urls == null || urls.length <= 0) {
            tokenInfo.put("permsVerify", false);
            return tokenInfo;
        }
        boolean bol = false;
        for (String url : urls) {
            bol = accessUrl.startsWith(url);
            if (bol) {
                break;
            }
        }
        tokenInfo.put("permsVerify", bol);
        return tokenInfo;
    }
}

